package cn.rengy.web.framework.wxmp.pay;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;

import jakarta.servlet.http.HttpServletRequest;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.rengy.lang.DataConverter;
import cn.rengy.lang.ResultEntity;
import cn.rengy.tool.core.util._NumberUtils;
import cn.rengy.tpa.wxmp.pay.H5PayParam;
import cn.rengy.tpa.wxmp.pay.MchKeyCallable;
import cn.rengy.tpa.wxmp.pay.PayManager;
import cn.rengy.tpa.wxmp.pay.exception.PayApiException;
import cn.rengy.tpa.wxmp.pay.exception.PayBusinessException;
import cn.rengy.tpa.wxmp.pay.exception.SignatureException;
import cn.rengy.tpa.wxmp.pay.protocol.pay_result_notify.PayResultDo;
import cn.rengy.tpa.wxmp.pay.protocol.unifiedorder.UnifiedorderDTO;
import cn.rengy.tpa.wxmp.pay.protocol.unifiedorder.UnifiedorderRspO;
import cn.rengy.web.framework.constants.Constants;
import cn.rengy.web.framework.id.IdGenerator;

import cn.rengy.web.framework.sql.DbService;
import cn.rengy.web.framework.util.GetSessionUtils;
import cn.rengy.web.framework.util._ServletUtil;
import cn.rengy.web.framework.wxmp.WxMerchant;
import cn.rengy.web.framework.wxmp.WxMerchantService;
import cn.rengy.web.framework.wxmp.WxmpConstants;
import cn.rengy.web.framework.wxmp.user.WxUserService;
@Service
public class WxPayService {
	private static Logger logger = LoggerFactory.getLogger(WxPayService.class);
	@Autowired
	private DbService dbService;
	@Autowired
	private DataConverter dataConverter;
	@Autowired
	private WxMerchantService wxMerchantService;
	@Autowired
	private MchKeyCallable mchKeyCallable;
	@Autowired(required = false)
	private WxPayOrderService wxPayOrderService;
	@Autowired
	private ScheduledExecutorService scheduledExecutorService;

	@Autowired(required = false)
	private BizOrderService bizOrderService;
	
	@Autowired
    private IdGenerator idGenerator;
	
	@Autowired
    private WxUserService wxUserService;
	/**
	 * 微信支付下单
	 * @param order_id
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity createWxOrder(Long order_id){
		OrderResult orderResult=new OrderResult();
		//boolean isPay=bizOrderService.isPaySuccess(order_id);
		BizOrder bizOrder=bizOrderService.lockOrder(order_id);
		
		if(bizOrder.getPay_status()==1){
			return ResultEntity.fail("订单已经支付了");
		}
		Long user_id=GetSessionUtils.getUserId();
		WxPayOrderPO wxPayOrderPO=this.dbService.queryForBean("select_wx_pay_order_by_order_id", WxPayOrderPO.class, order_id,user_id);
		if(wxPayOrderPO==null){
			String mch_id=bizOrder.getPay_mch_id();
			WxMerchant wxMerchant=wxMerchantService.getWxMerchant(mch_id);
			Long out_trade_no=idGenerator.nextId();//微信订单号
			//创建微信订单
			WxPayOrderDo wxPayOrder=new WxPayOrderDo();
			wxPayOrder.setOrder_id(order_id);
			wxPayOrder.setWxMerchant(wxMerchant);
			wxPayOrder.setAmount(bizOrder.getPayment_amount());
			wxPayOrder.setAppid(bizOrder.getAppid());
			wxPayOrder.setBody(bizOrder.getOrder_name());//加气站名称
			wxPayOrder.setMch_id(mch_id);
			wxPayOrder.setOut_trade_no(out_trade_no.toString());
			wxPayOrder.setProduct_id(bizOrder.getGoods_id());
			ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = servletRequestAttributes.getRequest();
			String spbill_create_ip=_ServletUtil.getClientIp(request);
			wxPayOrder.setSpbill_create_ip(spbill_create_ip);
			wxPayOrder.setTrade_type(bizOrder.getTradeType());
			wxPayOrder.setProfit_sharing(bizOrder.getIsProfitSharing());
			
			wxPayOrder.setUser_id(user_id);
			wxPayOrder.setOpenid(bizOrder.getOpenid());
			ResultEntity<?,UnifiedorderRspO> result=order(wxPayOrder);
			if(!result.isSuccess()) {
				return result;
			}
			orderResult.setCode_url(result.getData().getCode_url());
			orderResult.setOut_trade_no(out_trade_no);
			orderResult.setPrepay_id(result.getData().getPrepay_id());
			orderResult.setTrade_type(result.getData().getTrade_type());
			orderResult.setMweb_url(null);
			orderResult.setOut_trade_no(out_trade_no);
		}else {
			Integer order_status=wxPayOrderPO.getOrder_status();
			if((order_status!=null&&order_status.intValue()==2)) {
				return ResultEntity.fail("订单已经支付了");
			}
			orderResult.setCode_url(wxPayOrderPO.getCode_url());
			orderResult.setOut_trade_no(wxPayOrderPO.getOut_trade_no());
			orderResult.setPrepay_id(wxPayOrderPO.getPrepay_id());
			orderResult.setTrade_type(wxPayOrderPO.getTrade_type());
			orderResult.setMweb_url(null);
			orderResult.setOut_trade_no(wxPayOrderPO.getOut_trade_no());
		}
		return ResultEntity.ok(orderResult);
	}
	@Value("${domain:null}")
	private String domain;

	public ResultEntity<?,UnifiedorderRspO> order(WxPayOrderDo wxPayOrder)  {
		//String mch_id=wxPayOrder.getMch_id();
		WxMerchant merchant=wxPayOrder.getWxMerchant();
		BigDecimal amount=wxPayOrder.getAmount();
		UnifiedorderDTO unifiedorderDTO=new UnifiedorderDTO();
		unifiedorderDTO.setAppid(wxPayOrder.getAppid());
		//unifiedorderRequest.setAttach(attach);//附加数据 非必填
		unifiedorderDTO.setBody(wxPayOrder.getBody());
		//unifiedorderRequest.setDetail(detail);//商品详情 单品优惠字段(暂未上线) 非必填
		//unifiedorderRequest.setDevice_info(device_info);//自定义参数，可以为终端设备号(门店号或收银设备ID)，PC网页或公众号内支付可以传"WEB"
		//unifiedorderRequest.setFee_type(fee_type);//符合ISO 4217标准的三位字母代码，默认人民币：CNY， 非必填
		//unifiedorderRequest.setGoods_tag(goods_tag);//订单优惠标记，使用代金券或立减优惠功能时需要的参数，说明详见代金券或立减优惠
		unifiedorderDTO.setLimit_pay(wxPayOrder.getLimit_pay());//指定支付方式 上传此参数no_credit--可限制用户不能使用信用卡支付
		unifiedorderDTO.setMch_id(merchant.getMch_id());
		
		unifiedorderDTO.setNotify_url(domain.concat("/wxpay/notify"));//异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。
		unifiedorderDTO.setOpenid(wxPayOrder.getOpenid());//trade_type=JSAPI时（即公众号支付），此参数必传，此参数为微信用户在商户对应appid下的唯一标识
		unifiedorderDTO.setOut_trade_no(wxPayOrder.getOut_trade_no());//商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|* 且在同一个商户号下唯一
		unifiedorderDTO.setProduct_id(wxPayOrder.getProduct_id().toString());//trade_type=NATIVE时（即扫码支付），此参数必传。此参数为二维码中包含的商品ID，商户自行定义
		//ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
	   // HttpServletRequest request = servletRequestAttributes.getRequest();
		//String spbill_create_ip=IWebUtils.getClientIp(request);
		String spbill_create_ip=wxPayOrder.getSpbill_create_ip();
		unifiedorderDTO.setSpbill_create_ip(spbill_create_ip);//APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP
		//unifiedorderRequest.setTime_expire(time_expire);//订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010。注意：最短失效时间间隔必须大于5分钟
		//unifiedorderRequest.setTime_start(time_start);//订单生成时间，格式为yyyyMMddHHmmss
		//实际支付金额
		//BigDecimal payment_amount=new BigDecimal(pay_amount.toString());
		unifiedorderDTO.setAmount(amount);//订单总金额
		unifiedorderDTO.setTrade_type(wxPayOrder.getTrade_type());//取值如下：JSAPI，NATIVE，APP等
		unifiedorderDTO.setProfit_sharing(wxPayOrder.getProfit_sharing());
		ResultEntity<?,UnifiedorderRspO> result=PayManager.unifiedorder(dataConverter,merchant.getMch_key(),unifiedorderDTO);
		UnifiedorderRspO unifiedorderResponse=null;
		if(!result.isSuccess()) {
			return result;
		}
		unifiedorderResponse=result.getData();
		String prepay_id=unifiedorderResponse.getPrepay_id();
		//保存订单数据到数据库
		Map<String,Object> insert=new HashMap<String,Object>(17,1);
		insert.put("order_id", wxPayOrder.getOrder_id());
		insert.put("out_trade_no", wxPayOrder.getOut_trade_no());
		insert.put("total_fee", wxPayOrder.getAmount());
		insert.put("body", wxPayOrder.getBody());
		insert.put("prepay_id", prepay_id);
		insert.put("profit_sharing", wxPayOrder.getProfit_sharing().name());
		insert.put("trade_type", wxPayOrder.getTrade_type().name());
		insert.put("order_status", 0);//0待支付1支付成功2支付成功业务处理中
		insert.put("create_time", new Date());
		insert.put("user_id", wxPayOrder.getUser_id());
		insert.put("openid", wxPayOrder.getOpenid());
		insert.put("client_ip", spbill_create_ip);
		//insert.put("business_type", wxPayOrder.getBusiness_type());
		insert.put("appid", wxPayOrder.getAppid());
		insert.put("mch_id", wxPayOrder.getMch_id());
		insert.put("nickname", null);
		this.dbService.updateMapParameter("insert_wx_pay_order", insert);
		return ResultEntity.ok(unifiedorderResponse);
	}
	
		
	
	/**
	 * 已经生成预支付id后的支付
	 * @param param
	 * @param request
	 * @return
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws PayBusinessException 
	 * @throws PayApiException 
	 * @throws SignatureException 
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity<?,H5PayParam> payParam(Map<String,Object> param,HttpServletRequest request) throws SignatureException, PayApiException, PayBusinessException, IllegalAccessException, InvocationTargetException{
		//1.查询订单
		Long order_no=MapUtils.getLong(param, "id");//商户订单号
		Map<String,Object> order=this.dbService.queryForMap(false,"select_lock_wx_pay_order", order_no);
		if(order==null){
			return ResultEntity.fail("订单未找到");
		}
		int status=_NumberUtils.toInt(order.get("status"),0);
		if(status==2){
			return ResultEntity.fail("订单已支付");
		}
		Long order_id=MapUtils.getLong(order, "order_id");
		//Map<String,Object> bizOrder=this.dbService.queryForMap(false,"select_lock_order2",order_id);
		
		//int pay_status=_NumberUtils.toInt(bizOrder.get("pay_status"),0);
		if(bizOrderService.isPaySuccess(order_id)){
			return ResultEntity.fail("订单已经支付了");
		}
		String appid=(String)order.get("appid");
		String mch_id=(String)order.get("mch_id");
		WxMerchant wxMerchant=wxMerchantService.getWxMerchant(mch_id);
		String mch_key=wxMerchant.getMch_key();
		String prepay_id=(String)order.get("prepay_id");
		String nonce_str=RandomStringUtils.randomNumeric(32);
		Long time=System.currentTimeMillis()/1000;
		H5PayParam h5PayParam =PayManager.buildH5PayConfig(mch_key,appid,time.toString(), nonce_str, prepay_id);
		return ResultEntity.ok(h5PayParam);
	}
	
	/**
	 * 微信支付结果通知
	 * @param request
	 * @throws IOException
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class)
	public ResultEntity payNotify(HttpServletRequest request) throws IOException{
		ResultEntity<?,PayResultDo> result =PayManager.parsePayResultNotify(request.getInputStream(),mchKeyCallable);
		if(result.isSuccess()){
			PayResultDo payResultDo=result.getData();
			String out_trade_no=payResultDo.getOut_trade_no();
			String transaction_id=payResultDo.getTransaction_id();
			String openid=payResultDo.getOpenid();
			String appid=payResultDo.getAppid();
			//WxPayTradeType tradeType=payResultDo.getTrade_type();
			
			WxPayOrderPO wxPayOrderPO=this.dbService.queryForBean("lock_wx_pay_order", WxPayOrderPO.class, out_trade_no);
			if(wxPayOrderPO==null) {
				logger.error("微信订单查询为空：{}",out_trade_no);
				return ResultEntity.ok();
			}
			Integer orderStatus=wxPayOrderPO.getOrder_status();
			if(orderStatus.intValue()==WxmpConstants.WX_PAY_ORDER_STATUS_SUCCESS){
				logger.error("微信订单已经是支付成功状态：{}",out_trade_no);
				return ResultEntity.ok();
			}
			BigDecimal dbTotal_fee=wxPayOrderPO.getTotal_fee();
			BigDecimal returnTotal_fee=payResultDo.getTotal_fee();
				
			if(!dbTotal_fee.equals(returnTotal_fee)) {//订单金额不相等
				logger.error("支付结果通知订单金额和系统订单金额不一致");
				return ResultEntity.ok();
			}
			//1等待支付2支付成功3支付取消4支付失败
			//查询付款人昵称
			//从wx_user查询nickname
			//Map<String,Object> user=dbService.queryForMap(false,"select_get_user_by_openid", openid,appid);
			String nickname=null;
			//WxUserPO wxUserPO=wxUserService.getWxUser(openid, appid);
			//if(wxUserPO!=null) {
			//	nickname=wxUserPO.getNickname();
			//}
			//Map<String,Object> user=dbService.queryForMap(false,"select_get_user_from_sys_user", openid);
			//String user_id=MapUtils.getString(user, "user_id");
			
			wxPayOrderPO.setOrder_status(WxmpConstants.WX_PAY_ORDER_STATUS_SUCCESS);
			wxPayOrderPO.setOpenid(openid);
			wxPayOrderPO.setCash_fee(payResultDo.getCash_fee());
			wxPayOrderPO.setUser_id(null);
			wxPayOrderPO.setTransaction_id(transaction_id);
			wxPayOrderPO.setTime_end(payResultDo.getTime_end());
			wxPayOrderPO.setSettlement_total_fee(payResultDo.getSettlement_total_fee());
			wxPayOrderPO.setBank_type(payResultDo.getBank_type());
			wxPayOrderPO.setNickname(nickname);
			this.dbService.updateBeanParameter("update_wx_pay_order_success",wxPayOrderPO);
			//后续业务处理
			scheduledExecutorService.execute(new Runnable(){
				@Override
				public void run() {
					if(wxPayOrderService!=null) {
						wxPayOrderService.paysuccess(wxPayOrderPO);
					}
				}
			});
			return ResultEntity.ok();
		}else {
			return ResultEntity.fail(result.getCode(),result.getMessage());
		}
	}
	
    //abstract void process(Long order_sn);
	
}
